package com.dreamlin.gankio.base.ui

import android.os.Bundle
import android.view.*
import android.widget.Toast
import androidx.annotation.LayoutRes
import androidx.annotation.MenuRes
import androidx.annotation.StringRes
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import com.dreamlin.gankio.App
import com.dreamlin.gankio.base.model.BaseViewModel
import com.dreamlin.gankio.common.isFastDoubleClick

abstract class NoVMFragment<T : ViewDataBinding> : Fragment(), View.OnClickListener {

    private lateinit var loadingDialog: LoadingDialog

    protected lateinit var binding: T

    @get:LayoutRes
    protected abstract val layout: Int

    @MenuRes
    open fun getMenu(): Int = -0x01

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(inflater, layout, container, false) as T
        binding.lifecycleOwner = this
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        context?.let {
            loadingDialog = LoadingDialog(it)
        }
        initViews()
        initData()
    }

    protected abstract fun initViews()

    protected abstract fun initData()

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        if (getMenu() != -0x01) inflater.inflate(getMenu(), menu)
        else super.onCreateOptionsMenu(menu, inflater)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {

        when (item.itemId) {
            android.R.id.home -> {
                activity?.onBackPressed()
                return true
            }
        }
        return super.onOptionsItemSelected(item)
    }

    fun showLoading(msg: String? = null) {
        loadingDialog.show()
        loadingDialog.setLoadingMsg(msg)
    }

    fun hideLoading() {
        if (loadingDialog.isShowing) loadingDialog.dismiss()
    }

    fun toast(msg: String, duration: Int = Toast.LENGTH_SHORT) {
        Toast.makeText(activity, msg, duration).show()
    }

    fun toast(@StringRes string: Int, duration: Int = Toast.LENGTH_SHORT) {
        Toast.makeText(activity, string, duration).show()
    }

    override fun onClick(v: View?) {
        v?.let {
            if (!isFastDoubleClick(it.id)) {
                click(v)
            }
        }
    }

    protected abstract fun click(v: View)

}

open abstract class BaseFragment<T : ViewDataBinding, VM : BaseViewModel> : NoVMFragment<T>() {

    lateinit var viewModel: VM
    private var isCreated = false
    private var hasLoad = false

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        viewModel = App.getViewModelProvider().create(getVM())
        initObserver()
        return super.onCreateView(inflater, container, savedInstanceState)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        isCreated = true
        if (!hasLoad) {
            lazyLoad()
        }
    }

    abstract fun getVM(): Class<VM>

    //懒加载
    protected open fun lazyLoad() {
        hasLoad = true
    }

    //刷新加载,每次切换到该界面时都重新记载数据
    protected open fun refreshLoad() {
        hasLoad = true
    }

    //对应父NoVMFragment里的initData就是首次加载,create的时候加载

    //对应父NoVMFragment里的initData就是首次加载,create的时候加载
    /**
     * 这里需要注意，一般加载数据 三选一即可
     * initData仅会在Fragment创建时调用一次
     * lazyLoad会在界面可见时调用一次
     * refreshLoad会在界面每次可见时调用
     * 如果希望在Create的时候做一些预处理，比如希望每次都刷新数据，并且需要在创建时添加ViewModel的监听
     * 可以只在initData中添加监听，不要调用super.initData(),这样就不会影响另外两个加载方法的触发
     */
    override fun initData() {
        hasLoad = true
    }

    override fun onResume() {
        super.onResume()
        if (!hasLoad) {
            lazyLoad()
        }
        refreshLoad()
    }

    override fun onPause() {
        super.onPause()
    }

    private fun initObserver() {
        viewModel.initDialog(this, Observer {
            if (it.isShow) showLoading(it.msg)
            else hideLoading()
        })

        viewModel.initError(this, Observer {
            toast(it)
            onError()
        })
    }

    /**
     * 如果有刷新等逻辑
     * 需在错误逻辑里进行处理
     */
    open fun onError() {

    }
}